use std::net::IpAddr;

use bytes::{Buf, Bytes, BytesMut};
use tools::{
	error::Error,
	utils::bytes::{location_line_end, location_value_curr_line},
	ResultEx,
};
use tracing::{error, trace};

use crate::sip2::{utils::get_str, CRLF, SEPARATOR};

use super::{config::get_session_name_bytes, jump_line, Codec};

#[derive(Debug, Clone)]
pub struct Version {
	// inner: u8,
}
impl Version {
	pub(crate) fn new() -> Self {
		Self {
			// inner: 0
		}
	}
}
impl Codec for Version {
	fn write_to(&self, buf: &mut BytesMut) {
		buf.extend_from_slice(b"v=0\r\n");
	}

	fn from_bytes(buf: &mut Bytes) -> ResultEx<Self>
	where
		Self: Sized,
	{
		let end = location_line_end(buf);

		if buf[..end] == *b"v=0\r\n" {
			buf.advance(end);
			Ok(Self {
				// inner:0
			})
		} else {
			Err(Error::LogicalError("未知的版本号."))
		}
	}
}

/// 所有者/创建者和会话标识符
/// o=FreeSWITCH 1721349800 1721349801 IN IP4 183.218.88.21
#[derive(Debug, Clone)]
pub struct Origin {
	/// IP地址
	///
	///   后两
	/// addrtype: 地址类型，可以是 IPV4 和 IPV6 两种地址类型；
	/// unicast-address：会话发起者的 IP 地址。
	pub address: IpAddr,
}
impl Origin {
	pub(crate) fn new(addr: IpAddr) -> Self {
		Self { address: addr }
	}
}
impl Codec for Origin {
	fn write_to(&self, buf: &mut BytesMut) {
		buf.extend_from_slice(b"o=- 1 1 IN ");
		match self.address {
			IpAddr::V4(addr) => {
				buf.extend_from_slice(b"IP4 ");
				buf.extend_from_slice(addr.to_string().as_bytes());
			}
			IpAddr::V6(addr) => {
				buf.extend_from_slice(b"IP6 ");
				buf.extend_from_slice(addr.to_string().as_bytes());
			}
		}

		buf.extend_from_slice(CRLF);
	}

	fn from_bytes(buf: &mut Bytes) -> ResultEx<Self>
	where
		Self: Sized,
	{
		//跳过'='这个字段
		// buf.advance(2);
		let end = location_line_end(buf);

		let mut split = buf[..end].split(SPLIT_FELD);
		//跳过前3个
		split.next();
		split.next();
		split.next();
		if let Some(b) = split.next() {
			if b != b"IN" {
				return Err(Error::LogicalError("不能解析非 IN 值"));
			}
		}
		let Some(ip_type) = split.next() else {
			return Err(Error::LogicalError("长度不够..没有拿到ip类型"));
		};
		let Some(add) = split.next() else {
			return Err(Error::LogicalError("长度不够..没有拿到地址"));
		};
		let ip = match ip_type {
			b"IP4" => get_str(add).parse::<IpAddr>()?,
			b"IP6" => get_str(add).parse::<IpAddr>()?,
			_ => return Err(Error::LogicalError("不能解析无效的地址类型")),
		};

		buf.advance(end);

		Ok(Self { address: ip })
	}
}

#[derive(Debug, Clone)]
pub struct SessionName {
	inner: Bytes,
}

impl Codec for SessionName {
	fn write_to(&self, buf: &mut BytesMut) {
		buf.extend_from_slice(b"s=");
		buf.extend_from_slice(&self.inner);
		buf.extend_from_slice(CRLF);
	}

	fn from_bytes(buf: &mut Bytes) -> ResultEx<Self>
	where
		Self: Sized,
	{
		jump_line(buf);

		Ok(Self {
			inner: get_session_name_bytes().clone(),
		})
	}
}

impl SessionName {
	pub fn new(inner: Bytes) -> Self {
		SessionName { inner }
	}
}
#[derive(Debug, Clone)]
pub struct Connection {
	pub address: IpAddr,
}
impl Connection {
	pub(crate) fn new(addr: IpAddr) -> Self {
		Self { address: addr }
	}
}

impl Codec for Connection {
	fn write_to(&self, buf: &mut BytesMut) {
		buf.extend_from_slice(b"c=IN ");
		match self.address {
			IpAddr::V4(addr) => {
				buf.extend_from_slice(b"IP4 ");
				buf.extend_from_slice(addr.to_string().as_bytes());
			}
			IpAddr::V6(addr) => {
				buf.extend_from_slice(b"IP6 ");
				buf.extend_from_slice(addr.to_string().as_bytes());
			}
		}

		buf.extend_from_slice(CRLF);
	}

	fn from_bytes(buf: &mut Bytes) -> ResultEx<Self>
	where
		Self: Sized,
	{
		//跳过'='这个字段
		buf.advance(2);
		let end = location_line_end(buf);

		let mut split = buf[..end].split(SPLIT_FELD);

		if let Some(b) = split.next() {
			if b != b"IN" {
				return Err(Error::LogicalError("不能解析非 IN 值"));
			}
		}
		let Some(ip_type) = split.next() else {
			return Err(Error::LogicalError("长度不够..没有拿到ip类型"));
		};
		let Some(add) = split.next() else {
			return Err(Error::LogicalError("长度不够..没有拿到地址"));
		};
		let ip = match ip_type {
			b"IP4" => get_str(add).parse::<IpAddr>()?,
			b"IP6" => get_str(add).parse::<IpAddr>()?,
			_ => return Err(Error::LogicalError("不能解析无效的地址类型")),
		};

		buf.advance(end);

		Ok(Self { address: ip })
	}
}

#[derive(Debug, Clone)]
pub struct Media {
	///这个是做为一个缓存用处,目的是为加快生成速度
	cache: Bytes,
	pub media_type: MediaType,
	pub rtp_port: u16,
	pub rtcp_port: u16,
	pub proto: ProtoType,
	pub attribs: Vec<RtpItem>,
	///做为a属性内的ptime的值.目的是拿出来,方便处理.
	pub ptime: u16,
	///每一个media的连接地址.
	pub c: Option<Connection>,
	pub direction: MadiaDirection,
}

impl Codec for Media {
	fn write_to(&self, buf: &mut BytesMut) {
		buf.extend_from_slice(b"m=");
		self.media_type.write_to(buf);
		buf.extend_from_slice(self.rtp_port.to_string().as_bytes());

		if !self.cache.is_empty() {
			buf.extend_from_slice(&self.cache);
		} else {
			self.write_content(buf);
		}
	}

	fn from_bytes(buf: &mut Bytes) -> ResultEx<Self>
	where
		Self: Sized,
	{
		//跳过'='这个字段
		buf.advance(2);
		let end = location_line_end(buf);

		let mut split = buf[..end].split(SPLIT_FELD);
		let media_type = MediaType::from_bytes(
			split
				.next()
				.ok_or(Error::LogicalError("没有足够多的长度"))?,
		)?;

		let port = split
			.next()
			.ok_or(Error::LogicalError("没有足够多的长度"))?;
		let port = get_str(port).parse::<u16>()?;
		let proto = ProtoType::from_bytes(
			split
				.next()
				.ok_or(Error::LogicalError("没有足够多的长度"))?,
		)?;

		let mut rtps: Vec<RtpItem> = Vec::with_capacity(10);
		for item in split {
			if item.is_empty() {
				continue;
			}
			rtps.push(RtpItem::from_code(get_str(item).parse()?));
		}

		buf.advance(end);
		//到这里已经可以有一个默认的值出来.然后再根据下面的进行修改配置....
		let mut sf = Self {
			//从byters转过来的,是不需要切缓存的,即便是有用到,也使用生成就好.
			cache: Bytes::default(),
			media_type,
			rtp_port: port,
			rtcp_port: 0,
			proto,
			attribs: rtps,
			ptime: 20,
			c: None,
			direction: MadiaDirection::SendRecv,
		};

		//解析跟在后面的值.直到碰到下一个m,或者完全结束
		while !buf.is_empty() && buf[0] != b'm' {
			sf.set_media_field(buf.split_to(location_line_end(buf)));
		}

		Ok(sf)
	}
}

impl Media {
	///根据配置文件获取一个完整的
	pub fn from_config(m_type: MediaType, proto: ProtoType, attrs: &Vec<u8>) -> Self {
		let mut attribs = Vec::with_capacity(10);
		attrs.iter().for_each(|id| {
			let mut item = RtpItem::from_code(*id);
			match id {
				8 => {
					item.value = Bytes::from_static(b"PCMA/8000\r\n");
				}
				101 => {
					item.fmtp = Bytes::from_static(b"0-15\r\n");
					item.value = Bytes::from_static(b"telephone-event/8000\r\n");
				}
				_ => {}
			}
			attribs.push(item);
		});

		let mut m = Self {
			cache: Bytes::new(),
			media_type: m_type,
			rtp_port: 0,
			rtcp_port: 0,
			proto,
			attribs,
			ptime: 20,
			c: None,
			direction: MadiaDirection::SendRecv,
		};

		let mut buf = BytesMut::with_capacity(2048);
		m.write_content(&mut buf);
		m.cache = buf.freeze();

		m
	}
	///将内容部分(端口后面),写入缓存内.
	fn write_content(&self, buf: &mut BytesMut) {
		buf.extend_from_slice(SEPARATOR);
		self.proto.write_to(buf);
		//先写m的数字那一部分.然后再写详细内容.
		for item in &self.attribs {
			buf.extend_from_slice(SEPARATOR);
			buf.extend_from_slice(item.payload_type.to_string().as_bytes());
		}
		buf.extend_from_slice(CRLF);

		for item in &self.attribs {
			item.write_to(buf);
		}

		buf.extend_from_slice(b"a=ptime:");
		buf.extend_from_slice(self.ptime.to_string().as_bytes());
		buf.extend_from_slice(CRLF);
	}

	pub(crate) fn has_connect(&self) -> bool {
		self.c.is_some()
	}

	fn set_media_field(&mut self, mut buf: Bytes) {
		if buf.is_empty() {
			return;
		}

		let name = buf[0];

		match name {
			b'c' => {
				self.c = Some(Connection::from_bytes(&mut buf).unwrap());
			}
			b'a' => {
				let a_name_end = location_value_curr_line(&buf, 0, b':');
				match &buf[..a_name_end] {
					b"a=rtpmap" => {
						let id_end = location_value_curr_line(&buf, a_name_end, b' ');
						let Ok(id) = get_str(&buf[a_name_end + 1..id_end]).trim().parse::<u8>() else {
							trace!("rtpmap解析失败:{buf:?},跳过..");
							return;
						};
						buf.advance(id_end + 1);
						for item in self.attribs.iter_mut() {
							if item.payload_type == id {
								item.value = buf;
								break;
							}
						}
					}
					b"a=fmtp" => {
						let id_end = location_value_curr_line(&buf, a_name_end, b' ');
						let Ok(id) = get_str(&buf[a_name_end + 1..id_end]).trim().parse::<u8>() else {
							trace!("rtpmap解析失败:{buf:?},跳过..");
							return;
						};
						buf.advance(id_end + 1);
						for item in self.attribs.iter_mut() {
							if item.payload_type == id {
								item.fmtp = buf;
								break;
							}
						}
					}
					b"a=ptime" => {
						self.ptime = match get_str(&buf[a_name_end + 1..]).trim().parse() {
							Ok(t) => t,
							Err(e) => {
								error!("解码ptime失败,给默认值..异常:{e}");
								20
							}
						};
					}
					//目前没有解码ip地址.
					b"a=rtcp" => {
						self.rtcp_port = match get_str(&buf[a_name_end + 1..]).trim().parse() {
							Ok(v) => v,
							Err(e) => {
								error!("解码rtcp失败,给默认值..异常:{e}");
								0
							}
						};
					}
					_ => {
						trace!("未处理的a内容值:{buf:?}");
					}
				}
			}
			_ => {
				trace!("没有处理的mediam的内容,buf:{:?}", buf);
			}
		}
	}

	///匹配两个media..得到匹配的相应结果
	/// 动态类型是以self的动态类型值来返回
	pub(crate) fn merge(&self, other: &Media) -> Self {
		let mut a_vec = Vec::with_capacity(self.attribs.len());

		for a in self.attribs.iter() {
			for o_a in other.attribs.iter() {
				if a.payload_type < 96 && a.payload_type == o_a.payload_type {
					a_vec.push(a.clone());

					break;
				}

				//因为96-127是动态类型,需要特殊处理.
				if a.payload_type >= 96 && a.value == o_a.value {
					//self如果不存在fmtp.则将fmtp复制过去.
					let mut new_a = a.clone();
					if a.fmtp.is_empty() {
						new_a.fmtp = o_a.fmtp.clone();
					}

					a_vec.push(new_a);

					break;
				}
			}
		}

		Self {
			cache: Bytes::default(),
			media_type: self.media_type,
			rtp_port: self.rtp_port,
			rtcp_port: self.rtcp_port,
			proto: self.proto,
			attribs: a_vec,
			ptime: self.ptime,
			c: self.c.clone(),
			direction: self.direction,
		}
	}
}

#[derive(Debug, Clone)]
pub struct Timing {
	pub start: u32,
	pub stop: u32,
}
impl Timing {
	pub(crate) fn new() -> Self {
		Self { start: 0, stop: 0 }
	}
}

impl Codec for Timing {
	fn write_to(&self, buf: &mut BytesMut) {
		buf.extend_from_slice(b"t=0 0\r\n");
		//保留一下,后续可能有用
		// buf.extend_from_slice(b"t=");
		// buf.extend_from_slice(self.start.to_string().as_bytes());
		// buf.extend_from_slice(b" ");
		// buf.extend_from_slice(self.stop.to_string().as_bytes());
		// buf.extend_from_slice(CRLF);
	}

	fn from_bytes(buf: &mut Bytes) -> ResultEx<Self>
	where
		Self: Sized,
	{
		jump_line(buf);

		Ok(Self { start: 0, stop: 0 })
	}
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum MediaType {
	Audio,
	Video,
	Text,
	Application,
	Message,
}

impl MediaType {
	fn write_to(&self, buf: &mut BytesMut) {
		match self {
			MediaType::Audio => buf.extend_from_slice(b"audio "),
			MediaType::Video => buf.extend_from_slice(b"video "),
			MediaType::Text => buf.extend_from_slice(b"text "),
			MediaType::Application => buf.extend_from_slice(b"application "),
			MediaType::Message => buf.extend_from_slice(b"message "),
		}
	}

	fn from_bytes(buf: &[u8]) -> ResultEx<Self> {
		match buf {
			b"audio" => Ok(MediaType::Audio),
			b"video" => Ok(MediaType::Video),
			b"text" => Ok(MediaType::Text),
			b"application" => Ok(MediaType::Application),
			b"message" => Ok(MediaType::Message),
			_ => Err(Error::LogicalError("不能解析无效的媒体类型")),
		}
	}
}

#[derive(Debug, Clone, Copy)]
pub enum ProtoType {
	RtpAvp,
}

impl ProtoType {
	fn write_to(&self, buf: &mut BytesMut) {
		match self {
			ProtoType::RtpAvp => buf.extend_from_slice(b"RTP/AVP"),
			// _ => {}
		}
	}

	fn from_bytes(bytes: &[u8]) -> ResultEx<Self> {
		match bytes {
			b"RTP/AVP" => Ok(ProtoType::RtpAvp),
			_ => Err(Error::MediaError("目前还不支持的协议类型")),
		}
	}
}

///保存某一个Rtpmap的内容值
#[derive(Debug, Clone)]
pub struct RtpItem {
	///相对应的fmtp 的值..目前不知道,所以直接将这个值保存一下备用.
	pub fmtp: Bytes,
	/// 名称,类似于a=rtpmap:102 AMR/8000 的 AMR/8000 的值.
	pub value: Bytes,
	/// 对应的负载类型的值...有些动态的值是会发生变化的.
	pub payload_type: u8,
}

impl RtpItem {
	///通过code得到一个RtpItem....
	fn from_code(id: u8) -> Self {
		Self {
			fmtp: Bytes::default(),
			value: Bytes::default(),
			payload_type: id,
		}
	}

	fn write_to(&self, buf: &mut BytesMut) {
		//有些不存在value的,就不再输出
		if !self.value.is_empty() {
			buf.extend_from_slice(b"a=rtpmap:");

			buf.extend_from_slice(self.payload_type.to_string().as_bytes());
			buf.extend_from_slice(b" ");

			buf.extend_from_slice(&self.value);
		}

		if !self.fmtp.is_empty() {
			buf.extend_from_slice(b"a=fmtp:");

			buf.extend_from_slice(self.payload_type.to_string().as_bytes());
			buf.extend_from_slice(b" ");

			buf.extend_from_slice(&self.fmtp);
			// buf.extend_from_slice(CRLF);
		}
	}

	pub(crate) fn is_tele_event(&self) -> bool {
		self.value.starts_with(b"telephone-event")
	}
}

static SPLIT_FELD: fn(&u8) -> bool = |b| *b == b' ' || *b == b'\r' || *b == b'\n';

#[derive(Debug, Clone, Copy)]
pub enum MadiaDirection {
	SendOnly,
	RecvOnly,
	SendRecv,
	InActive,
}

impl From<MadiaDirection> for &str {
	fn from(value: MadiaDirection) -> Self {
		match value {
			MadiaDirection::SendOnly => "sendonly",
			MadiaDirection::RecvOnly => "recvonly",
			MadiaDirection::SendRecv => "sendrecv",
			MadiaDirection::InActive => "inactive",
		}
	}
}

impl From<&[u8]> for MadiaDirection {
	fn from(value: &[u8]) -> Self {
		match value {
			b"sendonly" => MadiaDirection::SendOnly,
			b"recvonly" => MadiaDirection::RecvOnly,
			b"sendrecv" => MadiaDirection::SendRecv,
			b"inactive" => MadiaDirection::InActive,
			_ => panic!("不支持的媒体方向"),
		}
	}
}
